home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 10 / AACD 10.iso / AACD / Games / MAME / src / vidhrdw / popeye.c < prev    next >
C/C++ Source or Header  |  2000-05-04  |  13KB  |  488 lines

  1. /***************************************************************************
  2.  
  3.   vidhrdw.c
  4.  
  5.   Functions to emulate the video hardware of the machine.
  6.  
  7. ***************************************************************************/
  8.  
  9. #include "driver.h"
  10. #include "vidhrdw/generic.h"
  11.  
  12.  
  13.  
  14. unsigned char *popeye_videoram;
  15. size_t popeye_videoram_size;
  16. unsigned char *popeye_background_pos,*popeye_palette_bank;
  17. static unsigned char *dirtybuffer2;
  18. static struct osd_bitmap *tmpbitmap2;
  19.  
  20.  
  21.  
  22. /***************************************************************************
  23.  
  24.   Convert the color PROMs into a more useable format.
  25.  
  26.   Popeye has four color PROMS:
  27.   - 32x8 char palette
  28.   - 32x8 background palette
  29.   - two 256x4 sprite palette
  30.  
  31.   The char and sprite PROMs are connected to the RGB output this way:
  32.  
  33.   bit 7 -- 220 ohm resistor  -- BLUE (inverted)
  34.         -- 470 ohm resistor  -- BLUE (inverted)
  35.         -- 220 ohm resistor  -- GREEN (inverted)
  36.         -- 470 ohm resistor  -- GREEN (inverted)
  37.         -- 1  kohm resistor  -- GREEN (inverted)
  38.         -- 220 ohm resistor  -- RED (inverted)
  39.         -- 470 ohm resistor  -- RED (inverted)
  40.   bit 0 -- 1  kohm resistor  -- RED (inverted)
  41.  
  42.   The background PROM is connected to the RGB output this way:
  43.  
  44.   bit 7 -- 470 ohm resistor  -- BLUE (inverted)
  45.         -- 680 ohm resistor  -- BLUE (inverted)
  46.         -- 470 ohm resistor  -- GREEN (inverted)
  47.         -- 680 ohm resistor  -- GREEN (inverted)
  48.         -- 1.2kohm resistor  -- GREEN (inverted)
  49.         -- 470 ohm resistor  -- RED (inverted)
  50.         -- 680 ohm resistor  -- RED (inverted)
  51.   bit 0 -- 1.2kohm resistor  -- RED (inverted)
  52.  
  53.   The bootleg is the same, but the outputs are not inverted.
  54.  
  55. ***************************************************************************/
  56. void popeye_vh_convert_color_prom(unsigned char *palette, unsigned short *colortable,const unsigned char *color_prom)
  57. {
  58.     int i;
  59.  
  60.  
  61.     /* background - darker than the others */
  62.     for (i = 0;i < 32;i++)
  63.     {
  64.         int bit0,bit1,bit2;
  65.  
  66.  
  67.         /* red component */
  68.         bit0 = (*color_prom >> 0) & 0x01;
  69.         bit1 = (*color_prom >> 1) & 0x01;
  70.         bit2 = (*color_prom >> 2) & 0x01;
  71.         *(palette++) = 0x1c * bit0 + 0x31 * bit1 + 0x47 * bit2;
  72.         /* green component */
  73.         bit0 = (*color_prom >> 3) & 0x01;
  74.         bit1 = (*color_prom >> 4) & 0x01;
  75.         bit2 = (*color_prom >> 5) & 0x01;
  76.         *(palette++) = 0x1c * bit0 + 0x31 * bit1 + 0x47 * bit2;
  77.         /* blue component */
  78.         bit0 = 0;
  79.         bit1 = (*color_prom >> 6) & 0x01;
  80.         bit2 = (*color_prom >> 7) & 0x01;
  81.         *(palette++) = 0x1c * bit0 + 0x31 * bit1 + 0x47 * bit2;
  82.  
  83.         color_prom++;
  84.     }
  85.  
  86.     /* characters */
  87.     for (i = 0;i < 16;i++)
  88.     {
  89.         int bit0,bit1,bit2;
  90.  
  91.  
  92.         /* red component */
  93.         bit0 = (*color_prom >> 0) & 0x01;
  94.         bit1 = (*color_prom >> 1) & 0x01;
  95.         bit2 = (*color_prom >> 2) & 0x01;
  96.         *(palette++) = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2;
  97.         /* green component */
  98.         bit0 = (*color_prom >> 3) & 0x01;
  99.         bit1 = (*color_prom >> 4) & 0x01;
  100.         bit2 = (*color_prom >> 5) & 0x01;
  101.         *(palette++) = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2;
  102.         /* blue component */
  103.         bit0 = 0;
  104.         bit1 = (*color_prom >> 6) & 0x01;
  105.         bit2 = (*color_prom >> 7) & 0x01;
  106.         *(palette++) = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2;
  107.  
  108.         color_prom++;
  109.     }
  110.  
  111.     color_prom += 16;    /* skip unused part of the PROM */
  112.  
  113.     /* sprites */
  114.     for (i = 0;i < 256;i++)
  115.     {
  116.         int bit0,bit1,bit2;
  117.  
  118.  
  119.         /* red component */
  120.         bit0 = (color_prom[0] >> 0) & 0x01;
  121.         bit1 = (color_prom[0] >> 1) & 0x01;
  122.         bit2 = (color_prom[0] >> 2) & 0x01;
  123.         *(palette++) = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2;
  124.         /* green component */
  125.         bit0 = (color_prom[0] >> 3) & 0x01;
  126.         bit1 = (color_prom[256] >> 0) & 0x01;
  127.         bit2 = (color_prom[256] >> 1) & 0x01;
  128.         *(palette++) = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2;
  129.         /* blue component */
  130.         bit0 = 0;
  131.         bit1 = (color_prom[256] >> 2) & 0x01;
  132.         bit2 = (color_prom[256] >> 3) & 0x01;
  133.         *(palette++) = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2;
  134.  
  135.         color_prom++;
  136.     }
  137.  
  138.  
  139.     /* palette entries 0-31 are directly used by the background */
  140.  
  141.     for (i = 0;i < 16;i++)    /* characters */
  142.     {
  143.         *(colortable++) = 0;    /* since chars are transparent, the PROM only */
  144.                                 /* stores the non transparent color */
  145.         *(colortable++) = i + 32;
  146.     }
  147.     for (i = 0;i < 256;i++)    /* sprites */
  148.     {
  149.         *(colortable++) = i + 32+16;
  150.     }
  151. }
  152.  
  153. void popeyebl_vh_convert_color_prom(unsigned char *palette, unsigned short *colortable,const unsigned char *color_prom)
  154. {
  155.     int i;
  156.  
  157.  
  158.     /* background - darker than the others */
  159.     for (i = 0;i < 32;i++)
  160.     {
  161.         int bit0,bit1,bit2;
  162.  
  163.  
  164.         /* red component */
  165.         bit0 = (*color_prom >> 0) & 0x01;
  166.         bit1 = (*color_prom >> 1) & 0x01;
  167.         bit2 = (*color_prom >> 2) & 0x01;
  168.         *(palette++) = 0x1c * bit0 + 0x31 * bit1 + 0x47 * bit2;
  169.         /* green component */
  170.         bit0 = (*color_prom >> 3) & 0x01;
  171.         bit1 = (*color_prom >> 4) & 0x01;
  172.         bit2 = (*color_prom >> 5) & 0x01;
  173.         *(palette++) = 0x1c * bit0 + 0x31 * bit1 + 0x47 * bit2;
  174.         /* blue component */
  175.         bit0 = 0;
  176.         bit1 = (*color_prom >> 6) & 0x01;
  177.         bit2 = (*color_prom >> 7) & 0x01;
  178.         *(palette++) = 0x1c * bit0 + 0x31 * bit1 + 0x47 * bit2;
  179.  
  180.         color_prom++;
  181.     }
  182.  
  183.     /* characters */
  184.     for (i = 0;i < 16;i++)
  185.     {
  186.         int bit0,bit1,bit2;
  187.  
  188.  
  189.         /* red component */
  190.         bit0 = (*color_prom >> 0) & 0x01;
  191.         bit1 = (*color_prom >> 1) & 0x01;
  192.         bit2 = (*color_prom >> 2) & 0x01;
  193.         *(palette++) = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2;
  194.         /* green component */
  195.         bit0 = (*color_prom >> 3) & 0x01;
  196.         bit1 = (*color_prom >> 4) & 0x01;
  197.         bit2 = (*color_prom >> 5) & 0x01;
  198.         *(palette++) = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2;
  199.         /* blue component */
  200.         bit0 = 0;
  201.         bit1 = (*color_prom >> 6) & 0x01;
  202.         bit2 = (*color_prom >> 7) & 0x01;
  203.         *(palette++) = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2;
  204.  
  205.         color_prom++;
  206.     }
  207.  
  208.     color_prom += 16;    /* skip unused part of the PROM */
  209.  
  210.     /* sprites */
  211.     for (i = 0;i < 256;i++)
  212.     {
  213.         int bit0,bit1,bit2;
  214.  
  215.  
  216.         /* red component */
  217.         bit0 = (color_prom[0] >> 0) & 0x01;
  218.         bit1 = (color_prom[0] >> 1) & 0x01;
  219.         bit2 = (color_prom[0] >> 2) & 0x01;
  220.         *(palette++) = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2;
  221.         /* green component */
  222.         bit0 = (color_prom[0] >> 3) & 0x01;
  223.         bit1 = (color_prom[256] >> 0) & 0x01;
  224.         bit2 = (color_prom[256] >> 1) & 0x01;
  225.         *(palette++) = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2;
  226.         /* blue component */
  227.         bit0 = 0;
  228.         bit1 = (color_prom[256] >> 2) & 0x01;
  229.         bit2 = (color_prom[256] >> 3) & 0x01;
  230.         *(palette++) = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2;
  231.  
  232.         color_prom++;
  233.     }
  234.  
  235.  
  236.     /* palette entries 0-31 are directly used by the background */
  237.  
  238.     for (i = 0;i < 16;i++)    /* characters */
  239.     {
  240.         *(colortable++) = 0;    /* since chars are transparent, the PROM only */
  241.                                 /* stores the non transparent color */
  242.         *(colortable++) = i + 32;
  243.     }
  244.     for (i = 0;i < 256;i++)    /* sprites */
  245.     {
  246.         *(colortable++) = i + 32+16;
  247.     }
  248. }
  249.  
  250.  
  251.  
  252. /***************************************************************************
  253.  
  254.   Start the video hardware emulation.
  255.  
  256. ***************************************************************************/
  257. int popeye_vh_start(void)
  258. {
  259.     if (generic_vh_start() != 0)
  260.         return 1;
  261.  
  262.     if ((dirtybuffer2 = malloc(popeye_videoram_size)) == 0)
  263.     {
  264.         generic_vh_stop();
  265.         return 1;
  266.     }
  267.     memset(dirtybuffer2,1,popeye_videoram_size);
  268.  
  269.     if ((tmpbitmap2 = osd_create_bitmap(Machine->drv->screen_width,Machine->drv->screen_height)) == 0)
  270.     {
  271.         free(dirtybuffer2);
  272.         generic_vh_stop();
  273.         return 1;
  274.     }
  275.  
  276.     return 0;
  277. }
  278.  
  279.  
  280. /***************************************************************************
  281.  
  282.   Stop the video hardware emulation.
  283.  
  284. ***************************************************************************/
  285. void popeye_vh_stop(void)
  286. {
  287.     osd_free_bitmap(tmpbitmap2);
  288.     free(dirtybuffer2);
  289.     generic_vh_stop();
  290. }
  291.  
  292.  
  293.  
  294. WRITE_HANDLER( popeye_videoram_w )
  295. {
  296.     if (data & 0x80)    /* write to the upper nibble */
  297.     {
  298.         if ((popeye_videoram[offset] & 0xf0) != ((data << 4) & 0xf0))
  299.         {
  300.             dirtybuffer2[offset] = 1;
  301.  
  302.             popeye_videoram[offset] = (popeye_videoram[offset] & 0x0f) | ((data << 4) & 0xf0);
  303.         }
  304.     }
  305.     else    /* write to the lower nibble */
  306.     {
  307.         if ((popeye_videoram[offset] & 0x0f) != (data & 0x0f))
  308.         {
  309.             dirtybuffer2[offset] = 1;
  310.  
  311.             popeye_videoram[offset] = (popeye_videoram[offset] & 0xf0) | (data & 0x0f);
  312.         }
  313.     }
  314. }
  315.  
  316.  
  317.  
  318. WRITE_HANDLER( popeye_palettebank_w )
  319. {
  320.     if ((data & 0x08) != (*popeye_palette_bank & 0x08))
  321.     {
  322.         memset(dirtybuffer,1,videoram_size);
  323.         memset(dirtybuffer2,1,popeye_videoram_size);
  324.     }
  325.  
  326.     *popeye_palette_bank = data;
  327. }
  328.  
  329.  
  330.  
  331. /***************************************************************************
  332.  
  333.   Draw the game screen in the given osd_bitmap.
  334.   Do NOT call osd_update_display() from this function, it will be called by
  335.   the main emulation engine.
  336.  
  337. ***************************************************************************/
  338. void popeye_vh_screenrefresh(struct osd_bitmap *bitmap,int full_refresh)
  339. {
  340.     int offs;
  341.  
  342.  
  343.     /* for every character in the Video RAM, check if it has been modified */
  344.     /* since last time and update it accordingly. */
  345.     for (offs = popeye_videoram_size - 1 - 128;offs >= 128;offs--)
  346.     {
  347.         if (dirtybuffer2[offs])
  348.         {
  349.             int sx,sy,x,y,colour;
  350.  
  351.             dirtybuffer2[offs] = 0;
  352.  
  353.             sx = 8 * (offs % 64);
  354.             sy = 8 * (offs / 64) - 16;
  355.  
  356.             if (sx   >= Machine->drv->visible_area.min_x &&
  357.                 sx+7 <= Machine->drv->visible_area.max_x &&
  358.                 sy   >= Machine->drv->visible_area.min_y &&
  359.                 sy+7 <= Machine->drv->visible_area.max_y)
  360.             {
  361.                 /* this is slow, but the background doesn't change during game */
  362.  
  363.                 colour = Machine->pens[(popeye_videoram[offs] & 0x0f) + 2*(*popeye_palette_bank & 0x08)];
  364.                 for (y = 0; y < 4; y++)
  365.                 {
  366.                     for (x = 0; x < 8; x++)
  367.                     {
  368.                         plot_pixel(tmpbitmap2, sx+x, sy+y, colour);
  369.                     }
  370.                 }
  371.  
  372.                 colour = Machine->pens[(popeye_videoram[offs] >> 4) + 2*(*popeye_palette_bank & 0x08)];
  373.                 for (y = 4;y < 8;y++)
  374.                 {
  375.                     for (x = 0; x < 8; x++)
  376.                     {
  377.                         plot_pixel(tmpbitmap2, sx+x, sy+y, colour);
  378.                     }
  379.                 }
  380.             }
  381.         }
  382.     }
  383.  
  384.     {
  385.         static int lastpos[2] = { -1, -1 };
  386.  
  387.         if (popeye_background_pos[0] != lastpos[0] ||
  388.             popeye_background_pos[1] != lastpos[1])
  389.         {
  390.             /* mark the whole screen dirty if we're scrolling */
  391.             osd_mark_dirty (Machine->drv->visible_area.min_x, Machine->drv->visible_area.min_y,
  392.                 Machine->drv->visible_area.max_x, Machine->drv->visible_area.max_y, 0);
  393.             lastpos[0] = popeye_background_pos[0];
  394.             lastpos[1] = popeye_background_pos[1];
  395.         }
  396.     }
  397.  
  398.     if (popeye_background_pos[0] == 0)    /* no background */
  399.     {
  400.         for (offs = videoram_size - 1;offs >= 0;offs--)
  401.         {
  402.             if (dirtybuffer[offs])
  403.             {
  404.                 int sx,sy;
  405.  
  406.                 dirtybuffer[offs] = 0;
  407.  
  408.                 sx = 16 * (offs % 32);
  409.                 sy = 16 * (offs / 32) - 16;
  410.  
  411.                 drawgfx(tmpbitmap,Machine->gfx[0],
  412.                         videoram[offs],colorram[offs],
  413.                         0,0,sx,sy,
  414.                         &Machine->drv->visible_area,TRANSPARENCY_NONE,0);
  415.             }
  416.         }
  417.  
  418.  
  419.         /* copy the frontmost playfield (should be in front of sprites, but never mind) */
  420.         copybitmap(bitmap,tmpbitmap,0,0,0,0,&Machine->drv->visible_area,TRANSPARENCY_NONE,0);
  421.     }
  422.     else
  423.     {
  424.         /* copy the background graphics */
  425.  
  426.            int x = 400 - 2 * popeye_background_pos[0];
  427.         int y = 2 * (256 - popeye_background_pos[1]);
  428.  
  429.         copybitmap(bitmap,tmpbitmap2,0,0,
  430.             x,
  431.             y,
  432.             &Machine->drv->visible_area,TRANSPARENCY_NONE,0);
  433.     }
  434.  
  435.  
  436.     /* Draw the sprites. Note that it is important to draw them exactly in this */
  437.     /* order, to have the correct priorities. */
  438.     for (offs = 0;offs < spriteram_size;offs += 4)
  439.     {
  440.         int code,color;
  441.  
  442.         /*
  443.          * offs+3:
  444.          * bit 7 ?
  445.          * bit 6 ?
  446.          * bit 5 ?
  447.          * bit 4 MSB of sprite code
  448.          * bit 3 vertical flip
  449.          * bit 2 sprite bank
  450.          * bit 1 \ color (with bit 2 as well)
  451.          * bit 0 /
  452.          */
  453.  
  454.         code = (spriteram[offs + 2] & 0x7f) + ((spriteram[offs + 3] & 0x10) << 3)
  455.                             + ((spriteram[offs + 3] & 0x04) << 6);
  456.         color = (spriteram[offs + 3] & 0x07) + 8*(*popeye_palette_bank & 0x07);
  457.  
  458.         if (spriteram[offs] != 0)
  459.             drawgfx(bitmap,Machine->gfx[1],
  460.                     code ^ 0x1ff,
  461.                     color,
  462.                     spriteram[offs + 2] & 0x80,spriteram[offs + 3] & 0x08,
  463.         /* sprite placement IS correct - the squares on level 1 leave one pixel */
  464.         /* of the house background uncovered */
  465.                     2*(spriteram[offs])-7,2*(256-spriteram[offs + 1]) - 16,
  466.                     &Machine->drv->visible_area,TRANSPARENCY_PEN,0);
  467.     }
  468.  
  469.  
  470.     if (popeye_background_pos[0] != 0)    /* background is present */
  471.     {
  472.         /* draw the frontmost playfield. They are characters, but draw them as sprites */
  473.         for (offs = videoram_size - 1;offs >= 0;offs--)
  474.         {
  475.             int sx,sy;
  476.  
  477.  
  478.             sx = 16 * (offs % 32);
  479.             sy = 16 * (offs / 32) - 16;
  480.  
  481.             drawgfx(bitmap,Machine->gfx[0],
  482.                     videoram[offs],colorram[offs],
  483.                     0,0,sx,sy,
  484.                     &Machine->drv->visible_area,TRANSPARENCY_PEN,0);
  485.         }
  486.     }
  487. }
  488.